/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _H_LIBZLANG_ENCODING_
#define _H_LIBZLANG_ENCODING_

#include "zlang.h"

#include "openssl/err.h"
#include "openssl/ssl.h"
#include "openssl/evp.h"
#include "openssl/des.h"
#include "openssl/aes.h"
#include "openssl/rsa.h"
#include "openssl/md4.h"
#include "openssl/md5.h"
#include "openssl/sha.h"
#include "openssl/rsa.h"
#include "openssl/pem.h"
#include "openssl/x509.h"
#include "openssl/pkcs12.h"
#include "openssl/objects.h"
#include "openssl/bio.h"

#if OPENSSL_VERSION_NUMBER < 0x10100000L
#define EVP_MD_CTX_new			EVP_MD_CTX_create
#define EVP_MD_CTX_free			EVP_MD_CTX_destroy
#endif

#define CRYPTO_ECB_MODE			1
#define CRYPTO_CBC_MODE			2

#define CRYPTO_KEY_64BITS		64
#define CRYPTO_KEY_128BITS		128
#define CRYPTO_KEY_192BITS		192
#define CRYPTO_KEY_256BITS		256
#define CRYPTO_KEY_512BITS		512
#define CRYPTO_KEY_1024BITS		1024
#define CRYPTO_KEY_2048BITS		2048
#define CRYPTO_KEY_4096BITS		4096

#define CRYPTO_E_3			RSA_3
#define CRYPTO_E_F4			RSA_F4

#define CRYPTO_NO_PADDING		RSA_NO_PADDING
#define CRYPTO_ZERO_PADDING		0
#define CRYPTO_PKCS7_PADDING		7
#define CRYPTO_PKCS1_PADDING		RSA_PKCS1_PADDING
#define CRYPTO_PKCS1_OAEP_PADDING	RSA_PKCS1_OAEP_PADDING

#define CRYPTO_NID_MD5			NID_md5
#define CRYPTO_NID_SHA1			NID_sha1
#define CRYPTO_NID_SHA224		NID_sha224
#define CRYPTO_NID_SHA256		NID_sha256
#define CRYPTO_NID_SHA384		NID_sha384
#define CRYPTO_NID_SHA512		NID_sha512
#define CRYPTO_NID_MD5_SHA1		NID_md5_sha1

#define DIGEST_OBJECT(_digest_,_DIGEST_) \
struct ZlangDirectProperty_##_digest_ \
{ \
	int	dummy ; \
} ; \
\
ZlangInvokeFunction ZlangInvokeFunction_##_digest_##_Digest_string; \
int ZlangInvokeFunction_##_digest_##_Digest_string( struct ZlangRuntime *rt , struct ZlangObject *obj ) \
{ \
	struct ZlangObject	*in1 = GetInputParameterInLocalObjectStack(rt,1) ; \
	struct ZlangObject	*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	char			*data = NULL ; \
	int32_t			data_len ; \
	char			digest[ _DIGEST_##_DIGEST_LENGTH ] ; \
	unsigned char		*pret = NULL ; \
	\
	CallRuntimeFunction_string_GetStringValue( rt , in1 , & data , & data_len ); \
	\
	pret = _DIGEST_( (unsigned char *)data , (unsigned long)data_len , (unsigned char *)digest ) ; \
	if( pret == NULL ) \
	{ \
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , #_DIGEST_ " failed" ) \
		UnreferObject( rt , out1 ); \
		return ThrowErrorException( rt , EXCEPTION_CODE_GENERAL , EXCEPTION_MESSAGE_DIGEST_FAILED ); \
	} \
	\
	CallRuntimeFunction_string_SetStringValue( rt , out1 , digest , _DIGEST_##_DIGEST_LENGTH ); \
	\
	return 0; \
} \
\
ZlangInvokeFunction ZlangInvokeFunction_##_digest_##_Digest_string_string; \
int ZlangInvokeFunction_##_digest_##_Digest_string_string( struct ZlangRuntime *rt , struct ZlangObject *obj ) \
{ \
	struct ZlangObject	*in1 = GetInputParameterInLocalObjectStack(rt,1) ; \
	struct ZlangObject	*in2 = GetInputParameterInLocalObjectStack(rt,2) ; \
	struct ZlangObject	*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	char			*data = NULL ; \
	int32_t			data_len ; \
	char			*salt = NULL ; \
	int32_t			salt_len ; \
	_DIGEST_##_CTX		ctx ; \
	char			digest[ _DIGEST_##_DIGEST_LENGTH ] ; \
	int			nret = 0 ; \
	\
	CallRuntimeFunction_string_GetStringValue( rt , in1 , & data , & data_len ); \
	CallRuntimeFunction_string_GetStringValue( rt , in2 , & salt , & salt_len ); \
	\
	_DIGEST_##_Init( & ctx ); \
	_DIGEST_##_Update( & ctx , (unsigned char *)data , (unsigned long)data_len ); \
	_DIGEST_##_Update( & ctx , (unsigned char *)salt , (unsigned long)salt_len ); \
	nret = _DIGEST_##_Final( (unsigned char *)digest , & ctx ); \
	if( nret != 1 ) \
	{ \
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , #_DIGEST_ "_Final failed[%d]" , nret ) \
		UnreferObject( rt , out1 ); \
		return ThrowErrorException( rt , EXCEPTION_CODE_GENERAL , EXCEPTION_MESSAGE_DIGEST_FAILED ); \
	} \
	\
	CallRuntimeFunction_string_SetStringValue( rt , out1 , digest , _DIGEST_##_DIGEST_LENGTH ); \
	\
	return 0; \
} \
\
ZlangCreateDirectPropertyFunction ZlangCreateDirectProperty_##_digest_; \
void *ZlangCreateDirectProperty_##_digest_( struct ZlangRuntime *rt , struct ZlangObject *obj ) \
{ \
	struct ZlangDirectProperty_##_digest_	*_digest_##_direct_prop = NULL ; \
	\
	_digest_##_direct_prop = (struct ZlangDirectProperty_##_digest_ *)ZLMALLOC( sizeof(struct ZlangDirectProperty_##_digest_) ) ; \
	if( _digest_##_direct_prop == NULL ) \
	{ \
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for entity" ) \
		return NULL; \
	} \
	memset( _digest_##_direct_prop , 0x00 , sizeof(struct ZlangDirectProperty_##_digest_) ); \
	\
	return _digest_##_direct_prop; \
} \
\
ZlangDestroyDirectPropertyFunction ZlangDestroyDirectProperty_##_digest_; \
void ZlangDestroyDirectProperty_##_digest_( struct ZlangRuntime *rt , struct ZlangObject *obj ) \
{ \
	struct ZlangDirectProperty_##_digest_	*_digest_##_direct_prop = GetObjectDirectProperty(obj) ; \
	\
	ZLFREE( _digest_##_direct_prop ); \
	\
	return; \
} \
\
ZlangSummarizeDirectPropertySizeFunction ZlangSummarizeDirectPropertySize_##_digest_; \
void ZlangSummarizeDirectPropertySize_##_digest_( struct ZlangRuntime *rt , struct ZlangObject *obj , size_t *summarized_obj_size , size_t *summarized_direct_prop_size ) \
{ \
	SUMMARIZE_SIZE( summarized_direct_prop_size , sizeof(struct ZlangDirectProperty_##_digest_) ) \
	return; \
} \
\
static struct ZlangDirectFunctions direct_funcs_##_digest_ = \
	{ \
		ZLANG_OBJECT_##_digest_ , /* char *ancestor_name */ \
		\
		ZlangCreateDirectProperty_##_digest_ , /* ZlangCreateDirectPropertyFunction *create_entity_func */ \
		ZlangDestroyDirectProperty_##_digest_ , /* ZlangDestroyDirectPropertyFunction *destroy_entity_func */ \
		\
		NULL , /* ZlangFromCharPtrFunction *from_char_ptr_func */ \
		NULL , /* ZlangToStringFunction *to_string_func */ \
		NULL , /* ZlangFromDataPtrFunction *from_data_ptr_func */ \
		NULL , /* ZlangGetDataPtrFunction *get_data_ptr_func */ \
		\
		NULL , /* ZlangOperatorFunction *oper_PLUS_func */ \
		NULL , /* ZlangOperatorFunction *oper_MINUS_func */ \
		NULL , /* ZlangOperatorFunction *oper_MUL_func */ \
		NULL , /* ZlangOperatorFunction *oper_DIV_func */ \
		NULL , /* ZlangOperatorFunction *oper_MOD_func */ \
		\
		NULL , /* ZlangUnaryOperatorFunction *unaryoper_NEGATIVE_func */ \
		NULL , /* ZlangUnaryOperatorFunction *unaryoper_NOT_func */ \
		NULL , /* ZlangUnaryOperatorFunction *unaryoper_BIT_REVERSE_func */ \
		NULL , /* ZlangUnaryOperatorFunction *unaryoper_PLUS_PLUS_func */ \
		NULL , /* ZlangUnaryOperatorFunction *unaryoper_MINUS_MINUS_func */ \
		\
		NULL , /* ZlangCompareFunction *comp_EGUAL_func */ \
		NULL , /* ZlangCompareFunction *comp_NOTEGUAL_func */ \
		NULL , /* ZlangCompareFunction *comp_LT_func */ \
		NULL , /* ZlangCompareFunction *comp_LE_func */ \
		NULL , /* ZlangCompareFunction *comp_GT_func */ \
		NULL , /* ZlangCompareFunction *comp_GE_func */ \
		\
		NULL , /* ZlangLogicFunction *logic_AND_func */ \
		NULL , /* ZlangLogicFunction *logic_OR_func */ \
		\
		NULL , /* ZlangLogicFunction *bit_AND_func */ \
		NULL , /* ZlangLogicFunction *bit_XOR_func */ \
		NULL , /* ZlangLogicFunction *bit_OR_func */ \
		NULL , /* ZlangLogicFunction *bit_MOVELEFT_func */ \
		NULL , /* ZlangLogicFunction *bit_MOVERIGHT_func */ \
		\
		ZlangSummarizeDirectPropertySize_##_digest_ , /* ZlangSummarizeDirectPropertySizeFunction *summarize_direct_prop_size_func */ \
	} ; \
\
ZlangImportObjectFunction ZlangImportObject_##_digest_; \
struct ZlangObject *ZlangImportObject_##_digest_( struct ZlangRuntime *rt ) \
{ \
	struct ZlangObject	*obj = NULL ; \
	struct ZlangFunction	*func = NULL ; \
	int			nret = 0 ; \
	\
	nret = ImportObject( rt , & obj , ZLANG_OBJECT_##_digest_ , & direct_funcs_##_digest_ , sizeof(struct ZlangDirectFunctions) , NULL ) ; \
	if( nret ) \
	{ \
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_LINK_FUNC_TO_ENTITY , "import object to global objects heap" ) \
		return NULL; \
	} \
	\
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_##_digest_##_Digest_string , ZLANG_OBJECT_string , "Digest" , ZLANG_OBJECT_string,NULL , NULL ) ; \
	if( func == NULL ) \
		return NULL; \
	\
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_##_digest_##_Digest_string_string , ZLANG_OBJECT_string , "Digest" , ZLANG_OBJECT_string,NULL , ZLANG_OBJECT_string,NULL , NULL ) ; \
	if( func == NULL ) \
		return NULL; \
	\
	return obj ; \
} \

#define SM3_DIGEST_LENGTH	32

#define EVP_DIGEST_OBJECT(_digest_,_DIGEST_) \
struct ZlangDirectProperty_##_digest_ \
{ \
	int	dummy ; \
} ; \
\
ZlangInvokeFunction ZlangInvokeFunction_##_digest_##_Digest_string; \
int ZlangInvokeFunction_##_digest_##_Digest_string( struct ZlangRuntime *rt , struct ZlangObject *obj ) \
{ \
	struct ZlangObject	*in1 = GetInputParameterInLocalObjectStack(rt,1) ; \
	struct ZlangObject	*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	EVP_MD_CTX		*ctx = NULL ; \
	char			*data = NULL ; \
	int32_t			data_len ; \
	char			digest[ _DIGEST_##_DIGEST_LENGTH ] ; \
	unsigned int		digest_len ; \
	int			nret = 0 ; \
	\
	CallRuntimeFunction_string_GetStringValue( rt , in1 , & data , & data_len ); \
	\
	ctx = EVP_MD_CTX_new() ; \
	if( ctx == NULL ) \
	{ \
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , #_DIGEST_ "EVP_MD_CTX_new failed" ) \
		UnreferObject( rt , out1 ); \
		return 0; \
	} \
	\
	nret = EVP_DigestInit_ex( ctx , EVP_##_digest_() , NULL ); \
	if( nret != 1 ) \
	{ \
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "EVP_DigestInit_ex failed[%d]" , nret ) \
		UnreferObject( rt , out1 ); \
		return 0; \
	} \
	\
	nret = EVP_DigestUpdate( ctx , (unsigned char *)data , (unsigned long)data_len ); \
	if( nret != 1 ) \
	{ \
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "EVP_DigestUpdate failed[%d]" , nret ) \
		UnreferObject( rt , out1 ); \
		return 0; \
	} \
	\
	nret = EVP_DigestFinal_ex( ctx , (unsigned char *)digest , & digest_len ); \
	if( nret != 1 || digest_len != _DIGEST_##_DIGEST_LENGTH ) \
	{ \
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "EVP_DigestFinal_ex failed[%d] digest_len[%ud]" , nret , digest_len ) \
		UnreferObject( rt , out1 ); \
		return 0; \
	} \
	\
	CallRuntimeFunction_string_SetStringValue( rt , out1 , digest , _DIGEST_##_DIGEST_LENGTH ); \
	\
	return 0; \
} \
\
ZlangInvokeFunction ZlangInvokeFunction_##_digest_##_Digest_string_string; \
int ZlangInvokeFunction_##_digest_##_Digest_string_string( struct ZlangRuntime *rt , struct ZlangObject *obj ) \
{ \
	struct ZlangObject	*in1 = GetInputParameterInLocalObjectStack(rt,1) ; \
	struct ZlangObject	*in2 = GetInputParameterInLocalObjectStack(rt,2) ; \
	struct ZlangObject	*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	EVP_MD_CTX		*ctx = NULL ; \
	char			*data = NULL ; \
	int32_t			data_len ; \
	char			*salt = NULL ; \
	int32_t			salt_len ; \
	char			digest[ _DIGEST_##_DIGEST_LENGTH ] ; \
	unsigned int		digest_len ; \
	int			nret = 0 ; \
	\
	CallRuntimeFunction_string_GetStringValue( rt , in1 , & data , & data_len ); \
	CallRuntimeFunction_string_GetStringValue( rt , in2 , & salt , & salt_len ); \
	\
	ctx = EVP_MD_CTX_new() ; \
	if( ctx == NULL ) \
	{ \
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , #_DIGEST_ "EVP_MD_CTX_new failed" ) \
		UnreferObject( rt , out1 ); \
		return 0; \
	} \
	\
	nret = EVP_DigestInit_ex( ctx , EVP_##_digest_() , NULL ); \
	if( nret != 1 ) \
	{ \
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "EVP_DigestInit_ex failed[%d]" , nret ) \
		UnreferObject( rt , out1 ); \
		return 0; \
	} \
	\
	nret = EVP_DigestUpdate( ctx , (unsigned char *)data , (unsigned long)data_len ); \
	if( nret != 1 ) \
	{ \
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "EVP_DigestUpdate failed[%d]" , nret ) \
		UnreferObject( rt , out1 ); \
		return 0; \
	} \
	\
	nret = EVP_DigestUpdate( ctx , (unsigned char *)salt , (unsigned long)salt_len ); \
	if( nret != 1 ) \
	{ \
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "EVP_DigestUpdate failed[%d]" , nret ) \
		UnreferObject( rt , out1 ); \
		return 0; \
	} \
	\
	nret = EVP_DigestFinal_ex( ctx , (unsigned char *)digest , & digest_len ); \
	if( nret != 1 || digest_len != _DIGEST_##_DIGEST_LENGTH ) \
	{ \
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "EVP_DigestFinal_ex failed[%d] digest_len[%ud]" , nret , digest_len ) \
		UnreferObject( rt , out1 ); \
		return 0; \
	} \
	\
	CallRuntimeFunction_string_SetStringValue( rt , out1 , digest , _DIGEST_##_DIGEST_LENGTH ); \
	\
	return 0; \
} \
\
ZlangCreateDirectPropertyFunction ZlangCreateDirectProperty_##_digest_; \
void *ZlangCreateDirectProperty_##_digest_( struct ZlangRuntime *rt , struct ZlangObject *obj ) \
{ \
	struct ZlangDirectProperty_##_digest_	*_digest_##_direct_prop = NULL ; \
	\
	_digest_##_direct_prop = (struct ZlangDirectProperty_##_digest_ *)ZLMALLOC( sizeof(struct ZlangDirectProperty_##_digest_) ) ; \
	if( _digest_##_direct_prop == NULL ) \
	{ \
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for entity" ) \
		return NULL; \
	} \
	memset( _digest_##_direct_prop , 0x00 , sizeof(struct ZlangDirectProperty_##_digest_) ); \
	\
	return _digest_##_direct_prop; \
} \
\
ZlangDestroyDirectPropertyFunction ZlangDestroyDirectProperty_##_digest_; \
void ZlangDestroyDirectProperty_##_digest_( struct ZlangRuntime *rt , struct ZlangObject *obj ) \
{ \
	struct ZlangDirectProperty_##_digest_	*_digest_##_direct_prop = GetObjectDirectProperty(obj) ; \
	\
	ZLFREE( _digest_##_direct_prop ); \
	\
	return; \
} \
\
ZlangSummarizeDirectPropertySizeFunction ZlangSummarizeDirectPropertySize_##_digest_; \
void ZlangSummarizeDirectPropertySize_##_digest_( struct ZlangRuntime *rt , struct ZlangObject *obj , size_t *summarized_obj_size , size_t *summarized_direct_prop_size ) \
{ \
	SUMMARIZE_SIZE( summarized_direct_prop_size , sizeof(struct ZlangDirectProperty_##_digest_) ) \
	return; \
} \
\
static struct ZlangDirectFunctions direct_funcs_##_digest_ = \
	{ \
		ZLANG_OBJECT_##_digest_ , /* char *ancestor_name */ \
		\
		ZlangCreateDirectProperty_##_digest_ , /* ZlangCreateDirectPropertyFunction *create_entity_func */ \
		ZlangDestroyDirectProperty_##_digest_ , /* ZlangDestroyDirectPropertyFunction *destroy_entity_func */ \
		\
		NULL , /* ZlangFromCharPtrFunction *from_char_ptr_func */ \
		NULL , /* ZlangToStringFunction *to_string_func */ \
		NULL , /* ZlangFromDataPtrFunction *from_data_ptr_func */ \
		NULL , /* ZlangGetDataPtrFunction *get_data_ptr_func */ \
		\
		NULL , /* ZlangOperatorFunction *oper_PLUS_func */ \
		NULL , /* ZlangOperatorFunction *oper_MINUS_func */ \
		NULL , /* ZlangOperatorFunction *oper_MUL_func */ \
		NULL , /* ZlangOperatorFunction *oper_DIV_func */ \
		NULL , /* ZlangOperatorFunction *oper_MOD_func */ \
		\
		NULL , /* ZlangUnaryOperatorFunction *unaryoper_NEGATIVE_func */ \
		NULL , /* ZlangUnaryOperatorFunction *unaryoper_NOT_func */ \
		NULL , /* ZlangUnaryOperatorFunction *unaryoper_BIT_REVERSE_func */ \
		NULL , /* ZlangUnaryOperatorFunction *unaryoper_PLUS_PLUS_func */ \
		NULL , /* ZlangUnaryOperatorFunction *unaryoper_MINUS_MINUS_func */ \
		\
		NULL , /* ZlangCompareFunction *comp_EGUAL_func */ \
		NULL , /* ZlangCompareFunction *comp_NOTEGUAL_func */ \
		NULL , /* ZlangCompareFunction *comp_LT_func */ \
		NULL , /* ZlangCompareFunction *comp_LE_func */ \
		NULL , /* ZlangCompareFunction *comp_GT_func */ \
		NULL , /* ZlangCompareFunction *comp_GE_func */ \
		\
		NULL , /* ZlangLogicFunction *logic_AND_func */ \
		NULL , /* ZlangLogicFunction *logic_OR_func */ \
		\
		NULL , /* ZlangLogicFunction *bit_AND_func */ \
		NULL , /* ZlangLogicFunction *bit_XOR_func */ \
		NULL , /* ZlangLogicFunction *bit_OR_func */ \
		NULL , /* ZlangLogicFunction *bit_MOVELEFT_func */ \
		NULL , /* ZlangLogicFunction *bit_MOVERIGHT_func */ \
		\
		ZlangSummarizeDirectPropertySize_##_digest_ , /* ZlangSummarizeDirectPropertySizeFunction *summarize_direct_prop_size_func */ \
	} ; \
\
ZlangImportObjectFunction ZlangImportObject_##_digest_; \
struct ZlangObject *ZlangImportObject_##_digest_( struct ZlangRuntime *rt ) \
{ \
	struct ZlangObject	*obj = NULL ; \
	struct ZlangFunction	*func = NULL ; \
	int			nret = 0 ; \
	\
	nret = ImportObject( rt , & obj , ZLANG_OBJECT_##_digest_ , & direct_funcs_##_digest_ , sizeof(struct ZlangDirectFunctions) , NULL ) ; \
	if( nret ) \
	{ \
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_LINK_FUNC_TO_ENTITY , "import object to global objects heap" ) \
		return NULL; \
	} \
	\
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_##_digest_##_Digest_string , ZLANG_OBJECT_string , "Digest" , ZLANG_OBJECT_string,NULL , NULL ) ; \
	if( func == NULL ) \
		return NULL; \
	\
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_##_digest_##_Digest_string_string , ZLANG_OBJECT_string , "Digest" , ZLANG_OBJECT_string,NULL , ZLANG_OBJECT_string,NULL , NULL ) ; \
	if( func == NULL ) \
		return NULL; \
	\
	return obj ; \
} \

unsigned char CheckKeyLen( int32_t key_len_type , int32_t key_len );

int ZeroPaddingBlockDataUnsafe( char *block_base , int block_data_len , int padding_size );
int Pkcs7PaddingBlockDataUnsafe( char *block_base , int block_data_len , int padding_size );
int PaddingBlockDataUnsafe( int padding_type , char *block_base , int block_data_len , int padding_size );

int ZeroUnpaddingData( char *block_base , int block_data_len );
int Pkcs7UnpaddingData( char *block_base , int block_data_len );
int UnpaddingData( int padding_type , char *block_base , int block_data_len );

int EvpCipherEncrypt( struct ZlangRuntime *rt , const EVP_CIPHER *cipher , char *key , char *iv , char *dec , int32_t dec_len , struct ZlangObject *enc_obj );
int EvpCipherDecrypt( struct ZlangRuntime *rt , const EVP_CIPHER *cipher , char *key , char *iv , char *enc , int32_t enc_len , struct ZlangObject *dec_obj );

struct ZlangDirectProperty_rsakey
{
	unsigned char	has_pubkey ;
	unsigned char	has_prikey ;
	RSA		*rsa ;
} ;

struct ZlangDirectProperty_rsa
{
	int		dummy ;
} ;

struct ZlangDirectProperty_sm2key
{
	unsigned char	has_pubkey ;
	unsigned char	has_prikey ;
	EVP_PKEY	*pkey ;
} ;

struct ZlangDirectProperty_sm2
{
	int		dummy ;
} ;

#define ZLANG_OBJECT_crypto	"crypto"
#define ZLANG_OBJECT_des	"des"
#define ZLANG_OBJECT_tripledes	"tripledes"
#define ZLANG_OBJECT_aes	"aes"
#define ZLANG_OBJECT_md4	"md4"
#define ZLANG_OBJECT_md5	"md5"
#define ZLANG_OBJECT_sha1	"sha1"
#define ZLANG_OBJECT_sha224	"sha224"
#define ZLANG_OBJECT_sha256	"sha256"
#define ZLANG_OBJECT_sha384	"sha384"
#define ZLANG_OBJECT_sha512	"sha512"
#define ZLANG_OBJECT_rsakey	"rsakey"
#define ZLANG_OBJECT_rsa	"rsa"
#ifdef SN_sm2
#ifndef OPENSSL_NO_SM2
#define ZLANG_OBJECT_sm2key	"sm2key"
#define ZLANG_OBJECT_sm2	"sm2"
#endif
#endif
#ifdef SN_sm3
#ifndef OPENSSL_NO_SM3
#define ZLANG_OBJECT_sm3	"sm3"
#endif
#endif
#ifdef SN_sm4_cbc
#ifndef OPENSSL_NO_SM4
#define ZLANG_OBJECT_sm4	"sm4"
#endif
#endif

#define EXCEPTION_MESSAGE_KEY_LEN_TYPE_INVALID				"key len type invalid"
#define EXCEPTION_MESSAGE_KEY_LEN_NOT_MATCHED_KEY_LEN_TYPE		"key len type not matched key len type"
#define EXCEPTION_MESSAGE_PADDING_TYPE_INVALID				"padding type invalid"
#define EXCEPTION_MESSAGE_PADDING_FAILED				"padding failed"
#define EXCEPTION_MESSAGE_UNPADDING_FAILED				"unpadding failed"
#define EXCEPTION_MESSAGE_ENC_LEN_INVALID				"enc len invalid"
#define EXCEPTION_MESSAGE_DIGEST_FAILED					"digest failed"
#define EXCEPTION_MESSAGE_RSAKEY_HASNT_PUBLIC_KEY			"rsakey hasn't public key"
#define EXCEPTION_MESSAGE_RSAKEY_HASNT_PRIVATE_KEY			"rsakey hasn't private key"
#define EXCEPTION_MESSAGE_RSA_ENCRYPT_FAILED				"rsa encrypt failed"
#define EXCEPTION_MESSAGE_RSA_DECRYPT_FAILED				"rsa decrypt failed"
#define EXCEPTION_MESSAGE_DEC_OR_DEC_LEN_INVALID			"dec or dec len invalid"
#define EXCEPTION_MESSAGE_ENC_OR_ENC_LEN_INVALID			"enc or enc len invalid"
#define EXCEPTION_MESSAGE_DATA_OR_DATA_LEN_INVALID			"data or data len invalid"
#define EXCEPTION_MESSAGE_EVP_MD_CTX_NEW_FAILED				"EVP_MD_CTX_new failed"
#define EXCEPTION_MESSAGE_EVP_PKEY_NEW_FAILED				"EVP_PEKY_new failed"
#define EXCEPTION_MESSAGE_EVP_PKEY_NEW_ID_FAILED			"EVP_PEKY_new_id failed"
#define EXCEPTION_MESSAGE_EVP_PKEY_SET_RSA_FAILED			"EVP_PEKY_set_rsa failed"
#define EXCEPTION_MESSAGE_EVP_PKEY_KEYGEN_INIT				"EVP_PEKY_keygen_init failed"
#define EXCEPTION_MESSAGE_EVP_SIGNINIT_FAILED				"EVP_SignInit failed"
#define EXCEPTION_MESSAGE_EVP_SIGNUPDATE_FAILED				"EVP_SignUpdate failed"
#define EXCEPTION_MESSAGE_EVP_SIGNFINAL_FAILED				"EVP_SignFinal failed"
#define EXCEPTION_MESSAGE_EVP_VERIFYINIT_FAILED				"EVP_VerifyInit failed"
#define EXCEPTION_MESSAGE_EVP_VERIFYUPDATE_FAILED			"EVP_VerifyUpdate failed"
#define EXCEPTION_MESSAGE_EVP_VERIFYFINAL_FAILED			"EVP_VerifyFinal failed"
#define EXCEPTION_MESSAGE_SIGN_DATA_OR_SIGN_DATA_LEN_INVALID		"sign data or sign data len invalid"
#define EXCEPTION_MESSAGE_EVP_VERIFYINIT_EX_FAILED			"EVP_VerifyInit_ex failed"
#define EXCEPTION_MESSAGE_EVP_VERIFYUPDATE_FAILED			"EVP_VerifyUpdate failed"
#define EXCEPTION_MESSAGE_GENERATE_KEY_PAIR_FAILED			"GenerateKeyPair failed"
#define EXCEPTION_MESSAGE_READ_RSA_PUBLIC_KEY_IN_FILE_FAILED		"read rsa public key in file failed"
#define EXCEPTION_MESSAGE_READ_RSA_PRIVATE_KEY_IN_FILE_FAILED		"read rsa private key in file failed"
#define EXCEPTION_MESSAGE_WRITE_RSA_PUBLIC_KEY_INTO_FILE_FAILED		"write rsa public key into file failed"
#define EXCEPTION_MESSAGE_WRITE_RSA_PRIVATE_KEY_INTO_FILE_FAILED	"write rsa private key into file failed"
#define EXCEPTION_MESSAGE_SM2KEY_HASNT_PRIVATE_KEY			"sm2key hasn't private key"
#define EXCEPTION_MESSAGE_SM2KEY_HASNT_PUBLIC_KEY			"sm2key hasn't public key"
#define EXCEPTION_MESSAGE_EVP_PKEY_CTX_SET_EC_PARAMGEN_CURVE_NID_FAILED	"EVP_PKEY_CTX_set_ec_paramgen_curve_nid failed"
#define EXCEPTION_MESSAGE_EVP_PKEY_KEYGEN_FAILED			"EVP_PKEY_keygen failed"
#define EXCEPTION_MESSAGE_READ_SM2_PUBLIC_KEY_IN_FILE_FAILED		"read sm2 public key in file failed"
#define EXCEPTION_MESSAGE_READ_SM2_PRIVATE_KEY_IN_FILE_FAILED		"read sm2 private key in file failed"
#define EXCEPTION_MESSAGE_WRITE_SM2_PUBLIC_KEY_INTO_FILE_FAILED		"write sm2 public key into file failed"
#define EXCEPTION_MESSAGE_WRITE_SM2_PRIVATE_KEY_INTO_FILE_FAILED	"write sm2 private key into file failed"
#define EXCEPTION_MESSAGE_EVP_CIPHER_ENCRYPT				"evp cipher encrypt"
#define EXCEPTION_MESSAGE_EVP_CIPHER_DECRYPT				"evp cipher decrypt"
#define EXCEPTION_MESSAGE_ENC_LEN_MUST_BE_MULTIPLE_OF_16		"enc len must be multiple of 16"
#define EXCEPTION_MESSAGE_EVP_VERIFYSIGNINIT_FAILED			"evp verifysigninit failed"
#define EXCEPTION_MESSAGE_SET_RSA_PUBLIC_KEY_FAILED			"set rsa public key failed"
#define EXCEPTION_MESSAGE_SET_RSA_PRIVATE_KEY_FAILED			"set rsa private key failed"

DLLEXPORT ZlangImportObjectsFunction ZlangImportObjects;
int ZlangImportObjects( struct ZlangRuntime *rt );

#endif

